package game.script;

import hx.geom.Point;
import game.data.ActionData.ActionType;
import hx.events.Keyboard;
import game.worlds.GameRole;

/**
 * AI控制器
 */
class AiScript {
	/**
	 * 控制角色
	 */
	public var role:GameRole;

	/**
	 * 是否启用
	 */
	public var enable(get, set):Bool;

	/**
	 * AI得思考速度，单位为秒，时间越短，AI行为变更越快
	 */
	public var aiSpeed = 0.3;

	/**
	 * 靠近战斗系数，控制角色的进攻概率
	 */
	public var nearFactor:Int = 50;

	/**
	 * 逃离战斗系数，控制角色的撤退概率
	 */
	public var awayFactor:Int = 30;

	/**
	 * 无所事事战斗系数，控制角色待机概率
	 */
	public var idleFactor:Int = 20;

	private var __enable:Bool = true;

	private function set_enable(value:Bool):Bool {
		__enable = value;
		this.role.releaseAllKeys();
		return value;
	}

	private function get_enable():Bool {
		return __enable;
	}

	public var dt:Float = 0.;

	public var actionType:AiActionType;

	public function new() {}

	public function update(dt:Float):Void {
		if (!this.__enable)
			return;

		var enemy = this.role.getTargetEnemy();
		if (enemy == null)
			return;

		this.dt += dt;
		if (this.dt > aiSpeed) {
			this.dt -= aiSpeed;
			// 更新行为
			var all = nearFactor + awayFactor + idleFactor;
			var random = Std.random(all);
			var actions = [nearFactor, awayFactor, idleFactor];
			var actionIndex = 0;
			for (i => value in actions) {
				if (random < value) {
					actionIndex = i;
					break;
				}
				random -= value;
			}
			if (actionIndex == 0 || this.role.isHitFly) {
				if ((enemy.jumping || this.role.isHitFly) && Std.random(100) > 80) {
					this.actionType = JUMP;
				} else
					this.actionType = NEAR;
			} else if (actionIndex == 1) {
				this.actionType = AWAY;
			} else if (actionIndex == 2) {
				this.actionType = IDLE;
			}
		}

		if (this.role.isSkilling) {
			@:privateAccess this.role.__attackTime = this.role.world.worldRunTime;
			return;
		}

		// 行为处理
		switch actionType {
			case NEAR:
				this.anywhereNear(enemy);
			case IDLE:
				this.idle(enemy);
			case AWAY:
				this.anywhereAway(enemy);
			case JUMP:
				this.anywhereNear(enemy, true);
		}
	}

	/**
	 * 靠近敌人
	 * @param enemy 
	 */
	public function anywhereNear(enemy:GameRole, isJump:Bool = false):Void {
		if (isJump) {
			if (!this.role.jumping || this.role.isHitFly)
				this.role.onKeyDown(this.role.keyReceiver.JUMP);
		}
		if (Point.distanceByFloat(enemy.x, enemy.y, this.role.x, this.role.y) > 60) {
			if (enemy.x > this.role.x) {
				this.role.onKeyDown(this.role.keyReceiver.RIGHT);
				this.role.onKeyUp(this.role.keyReceiver.LEFT);
			} else {
				this.role.onKeyDown(this.role.keyReceiver.LEFT);
				this.role.onKeyUp(this.role.keyReceiver.RIGHT);
			}
		}
		tryPlaySkill(enemy);
	}

	/**
	 * 远离敌人
	 * @param enemy
	 */
	public function anywhereAway(enemy:GameRole):Void {
		// if (Point.distanceByFloat(enemy.x, enemy.y, this.role.x, this.role.y) > 60) {
		if (enemy.x > this.role.x) {
			this.role.onKeyDown(this.role.keyReceiver.LEFT);
			this.role.onKeyUp(this.role.keyReceiver.RIGHT);
		} else {
			this.role.onKeyDown(this.role.keyReceiver.RIGHT);
			this.role.onKeyUp(this.role.keyReceiver.LEFT);
		}
		// }
	}

	/**
	 * 待机
	 * @param enemy 
	 */
	public function idle(enemy:GameRole):Void {
		this.role.releaseAllKeys();
	}

	/**
	 * 尝试释放技能
	 * @param enemy 
	 * @return Bool
	 */
	public function tryPlaySkill(enemy:GameRole):Bool {
		if (enemy.isSkilling)
			return false;
		for (data in this.role.roleData.actions) {
			if (this.role.cdData.isCDing(data.name))
				continue;
			switch data.type {
				case AUTO:
				case GROUND_SKILL:
					if (!this.role.jumping && tryHitDataSkill(enemy, data.name)) {
						this.role.playSkillFromKey(data.name);
						return true;
					}
				case AIR_SKILL:
					if (this.role.jumping && tryHitDataSkill(enemy, data.name)) {
						this.role.playSkillFromKey(data.name);
						return true;
					}
				case ALL_SKILL:
					if (tryHitDataSkill(enemy, data.name)) {
						this.role.playSkillFromKey(data.name);
						return true;
					}
			}
		}
		if (Std.random(100) > 80 && Point.distanceByFloat(enemy.x, enemy.y, this.role.x, this.role.y) < 300) {
			var skills = [
				for (data in this.role.roleData.actions) {
					data.name;
				}
			].filter(s -> {
				if (this.role.roleData.actions.exists(s)) {
					var action = this.role.roleData.actions.get(s);
					if (action.groupKeys != null && action.groupKeys.length > 0 && !this.role.cdData.isCDing(action.name)) {
						if (this.role.jumping && action.type == AIR_SKILL) {
							return true;
						} else if (action.type == GROUND_SKILL || action.type == GROUND_SKILL)
							return true;
					}
				}
				return false;
			});
			if (skills.length > 0) {
				this.role.playSkillFromKey(skills[Std.random(skills.length)]);
				return true;
			}
		}
		return false;
	}

	/**
	 * 尝试释放技能，会使用所有攻击块位置检测攻击范围，如果符合则会返回`true`，如果不在攻击范围内，则返回`false`。
	 */
	public function tryHitDataSkill(enemy:GameRole, skillName:String):Bool {
		var action = this.role.roleData.actions.get(skillName);
		for (data in action.frames) {
			if (data.collision != null) {
				if (data.testCollision(this.role, enemy.hitBody.shape)) {
					return true;
				}
			}
		}
		return false;
	}
}

enum abstract AiActionType(Int) to Int from Int {
	/**
	 * 接近敌人，有机会则会攻击
	 */
	var NEAR = 0;

	/**
	 * 待机，危险时则会防御
	 */
	var IDLE = 1;

	/**
	 * 远离敌人
	 */
	var AWAY = 2;

	/**
	 * 跳跃追击敌人，有机会则会攻击
	 */
	var JUMP = 3;
}
